using System;
using System.Collections;

namespace Crawler
{
	/// <summary>
	/// understands a store for storing downloads
	/// </summary>
	public class DownloadStore : IDownloadStore {
		Hashtable downloadStore = new Hashtable();
		public static IDownloadStore NULL_DOWNLOADSTORE = NullDownloadStore.NULL_DOWNLOADSTORE;
		private ICrawlerContext crawlerContext;
		public event ReferenceAddedToDownloadStoreHandler ReferenceAddedToDownloadStore;
		
		public DownloadStore(ICrawlerContext crawlerContext) {
			this.crawlerContext = crawlerContext ;
		}

		public int Count { 
			get{return downloadStore.Count;}
		}

		public void Add(IKey key, IResourceReference reference) {
			try {
				downloadStore.Add(key, reference);
				TriggerParsing(key);
			}catch(Exception e ){}
		}

		private void TriggerParsing(IKey key)
		{
			if (crawlerContext.UrlStackEmpty)
				OnReferenceAddedToDownloadStore(new ReferenceAddedToDownloadStoreArgs(key));
			else ReferenceAddedToDownloadStoreArgs.AddKeysToCachedQueue(key) ;
		}

		public IResourceReference GetResource(IKey key) {
			if(!downloadStore.ContainsKey(key))
				return ResourceReference.NULL_REFERENCE ;        			
			return downloadStore[key] as IResourceReference; 
		}

		public void Remove(Key Key) {
			downloadStore.Remove(Key);
		}

		private class NullDownloadStore : IDownloadStore {
			public static IDownloadStore NULL_DOWNLOADSTORE = new NullDownloadStore();

			private NullDownloadStore() {}
			#region IDownloadStore Members

			public int Count {
				get {
					return 0;
				}
			}

			public IResourceReference GetResource(IKey key) {
				return ResourceReference.NULL_REFERENCE;
			}

			public void Add(IKey Key, IResourceReference reference) {
			}

			public void Remove(Key Key) {
			}

			#endregion

		}

		protected virtual void OnReferenceAddedToDownloadStore(ReferenceAddedToDownloadStoreArgs args) {
			if (ReferenceAddedToDownloadStore != null)
				ReferenceAddedToDownloadStore(this, args);
		}
	}

	/// <summary>
	/// The delegate method provides a framework to handle the events that have been raised by the DownloadStore
	/// </summary>
	public delegate void ReferenceAddedToDownloadStoreHandler(object sender, ReferenceAddedToDownloadStoreArgs args);
}
